package pathfinder;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.PriorityQueue;

public class Truck {

  public char[][] map;
  //Y = daya angkut truk
  int x, y, Y, YCur;
  int xCur, yCur;
  ArrayList<Vendor> vendores;
  int N = 0;
  public LinkedList<Point> result;

  public Truck() {
    vendores = new ArrayList<>();
    result = new LinkedList<>();
    x = 0;
    y = 0;
    N = 0;
    xCur = 0;
    yCur = 0;
    YCur = 0;
  }
  
  public int breadhFirstSearch(int x, int y, int xDes, int yDes) {
    int cost = 0;
    LinkedList<Point> ll = new LinkedList<>();
    HashSet<String> h = new HashSet<>();
    Point p = new Point(x,y,xDes,yDes);
    ll.add(p);
    result.add(p);
    boolean get = false;
    while (!get) {
      Point t = ll.remove();
      result.add(t);
      h.add(twoIntToString(t.x, t.y));
      if (t.x < 0 || t.x >= map.length || t.y < 0 || t.y >= map[0].length) {
        continue;
      } else if (map[t.x][t.y] == '#') {
        continue;
      } else if (t.x == xDes && t.y == yDes) {
        get = true;
        cost += t.cost;
        xCur = t.x;
        yCur = t.y;
        if (xDes == this.x && yDes == this.y) {
          YCur = Y;
//          System.out.println("HAHAHA");
        } else {
          YCur--;
//          System.out.println("HEHEHE");
        }
      } else {
        if (!h.contains(twoIntToString(t.x + 1, t.y))) {
          ll.add(new Point(t.x + 1, t.y, t.xDes, t.yDes, t.cost + 1));
        }
        if (!h.contains(twoIntToString(t.x - 1, t.y))) {
          ll.add(new Point(t.x - 1, t.y, t.xDes, t.yDes, t.cost + 1));
        }
        if (!h.contains(twoIntToString(t.x, t.y + 1))) {
          ll.add(new Point(t.x, t.y + 1, t.xDes, t.yDes, t.cost + 1));
        }
        if (!h.contains(twoIntToString(t.x, t.y - 1))) {
          ll.add(new Point(t.x, t.y - 1, t.xDes, t.yDes, t.cost + 1));
        }
      }
    }
    return cost;
  }
  
  public int depthFirstSearch(int x, int y, int xDes, int yDes) {
    int cost = 0;
    LinkedList<Point> ll = new LinkedList<>();
    HashSet<String> h = new HashSet<>();
    Point p = new Point(x,y,xDes,yDes);
    ll.add(p);
    result.add(p);
    boolean get = false;
    while (!get) {
      Point t = ll.removeLast();
      result.add(t);
      h.add(twoIntToString(t.x, t.y));
      if (t.x < 0 || t.x >= map.length || t.y < 0 || t.y >= map[0].length) {
        continue;
      } else if (map[t.x][t.y] == '#') {
        continue;
      } else if (t.x == xDes && t.y == yDes) {
        get = true;
        cost += t.cost;
        xCur = t.x;
        yCur = t.y;
        if (xDes == this.x && yDes == this.y) {
          YCur = Y;
//          System.out.println("HAHAHA");
        } else {
          YCur--;
//          System.out.println("HEHEHE");
        }
      } else {
        if (!h.contains(twoIntToString(t.x + 1, t.y))) {
          ll.add(new Point(t.x + 1, t.y, t.xDes, t.yDes, t.cost + 1));
        }
        if (!h.contains(twoIntToString(t.x - 1, t.y))) {
          ll.add(new Point(t.x - 1, t.y, t.xDes, t.yDes, t.cost + 1));
        }
        if (!h.contains(twoIntToString(t.x, t.y + 1))) {
          ll.add(new Point(t.x, t.y + 1, t.xDes, t.yDes, t.cost + 1));
        }
        if (!h.contains(twoIntToString(t.x, t.y - 1))) {
          ll.add(new Point(t.x, t.y - 1, t.xDes, t.yDes, t.cost + 1));
        }
      }
    }
    return cost;
  }

  public int aStar(int x, int y, int xDes, int yDes) {
    int cost = 0;
    PriorityQueue<Point> pq = new PriorityQueue<>();
    HashSet<String> h = new HashSet<>();
    Point p = new Point(x, y, xDes, yDes);
    pq.add(p);
    result.add(p);
    boolean get = false;
    while (!get) {
      Point t = pq.remove();
      result.add(t);
//      System.out.println(result.size());
      h.add(twoIntToString(t.x, t.y));
      if (t.x < 0 || t.x >= map.length || t.y < 0 || t.y >= map[0].length) {
        continue;
      } else if (map[t.x][t.y] == '#') {
        continue;
      } else if (t.x == xDes && t.y == yDes) {
        get = true;
        cost += t.cost;
        xCur = t.x;
        yCur = t.y;
        if (xDes == this.x && yDes == this.y) {
          YCur = Y;
        } else {
          YCur--;
        }
      } else {
        if (!h.contains(twoIntToString(t.x + 1, t.y))) {
          pq.add(new Point(t.x + 1, t.y, t.xDes, t.yDes, t.cost + 1));
        }
        if (!h.contains(twoIntToString(t.x - 1, t.y))) {
          pq.add(new Point(t.x - 1, t.y, t.xDes, t.yDes, t.cost + 1));
        }
        if (!h.contains(twoIntToString(t.x, t.y + 1))) {
          pq.add(new Point(t.x, t.y + 1, t.xDes, t.yDes, t.cost + 1));
        }
        if (!h.contains(twoIntToString(t.x, t.y - 1))) {
          pq.add(new Point(t.x, t.y - 1, t.xDes, t.yDes, t.cost + 1));
        }
      }
    }
    return cost;
  }
  
  public String twoIntToString(int x, int y) {
    StringBuilder sb = new StringBuilder();
    sb.append(x);
    sb.append(y);
    return sb.toString();
  }

  public Vendor getVendorFromChar(char c) {
    for (int i = 0; i < vendores.size(); i++) {
      if (vendores.get(i).name.charAt(0) == c) {
        return vendores.get(i);
      }
    }
    return null;
  }

  public Vendor getShortestVendor(int machinenumber) {
    double minrange = Double.MAX_VALUE;
    int indexmin = 0;
    for (int i = 0; i < vendores.size(); i++) {
      if (vendores.get(i).machine.contains(machinenumber)) {
        double range = Math.sqrt(Math.pow(x - vendores.get(i).x, 2) + Math.pow(y - vendores.get(i).y, 2));
        if (range < minrange) {
          minrange = range;
          indexmin = i;
        }
      }
    }
//    System.out.println(vendores.get(indexmin).name);
    return vendores.get(indexmin);
  }

  public final void setVendores() {
    for (int i = 0; i < map.length; i++) {
      for (int j = 0; j < map[0].length; j++) {
        if (map[i][j] == '.' || map[i][j] == '#') {
          continue;
        }
        if (map[i][j] == 'P') {
          xCur = x = i;
          yCur = y = j;
        }
        for (int k = 0; k < vendores.size(); k++) {
          if (vendores.get(k).name.charAt(0) == map[i][j]) {
            vendores.get(k).x = i;
            vendores.get(k).y = j;
          }
        }
      }
    }
  }
}
